home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’89 / gadlife / source (ugly) / patch.menu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-14  |  9.1 KB  |  370 lines  |  [TEXT/KAHL]

  1. #include "main.h"
  2. #include "patch.h"
  3. #include "patch.menu.h"
  4.  
  5. /*******************************************************
  6. *                                                                *
  7. *    This currently works with    :                                        *
  8. *        normal menu selection.                                        *
  9. *        heierarchical menu selection.                                    *
  10. *        pop-up menu selection in DAs                                    *
  11. *    Should work with, but doesn't:                                        *
  12. *        tear-off menus, installed by other inits and things.                    *
  13. *    Known problems:                                                *
  14. *        may mess up with icons in menus.                                *
  15. *        may mess up with Pop-Up Menus in modal dialogs brought up by DAs.        *
  16. *                                                                *
  17. *******************************************************/
  18.  
  19. extern long            timer();
  20.  
  21. long                    oldPopUp, oldDragGray, oldDragThe, oldWaitMouse, 
  22.                     oldSysMenu, oldStillDown, oldAvail, oldDelay, oldCopyBits;
  23. int                    menuTrapsOn = 0, waitTrapOn = 0, popUpTrapOn = 0, 
  24.                     sysMenuActed = 0, delayTrapOn = 0;
  25. int                    isMyCopy = 1;
  26.  
  27. static rgnListHandle        menuRgns = NULL;
  28.  
  29. /*******************************************************
  30. *                                                                *
  31. *                                                                *
  32. *******************************************************/
  33.  
  34. WindowPeek nextUserWindow( theWindow )
  35.     WindowPeek    theWindow;
  36.     {
  37.     while( theWindow && theWindow->windowKind < userKind )
  38.         theWindow = theWindow->nextWindow;
  39.     return( theWindow );
  40.     }
  41.  
  42. /* Trouble here - dest may be either a BitMapPtr or a PixMapPtr.    */
  43.  
  44. fixWindows( dest, bounds, menuMask, when )
  45.     BitMap        *dest;
  46.     Rect            *bounds;
  47.     RgnHandle        menuMask;
  48.     long            when;
  49.     {
  50.     Rect            realBounds;
  51.     Point            off;
  52.     GrafPtr        savePort;
  53.     WindowPeek    theWindow;
  54.     RgnHandle        mask, selMask;
  55.     dataHandle    theDataHand;
  56.     dataPtr        theData;
  57.  
  58.     mask = NewRgn();
  59.     selMask = NewRgn();
  60.     theWindow = nextUserWindow( FrontWindow() );
  61.     GetPort( &savePort );
  62.     while( theWindow ) {
  63.         theDataHand = ( dataHandle )GetWRefCon( theWindow );
  64.         HLock( theDataHand );
  65.         theData = *theDataHand;
  66.         if( theData->changed > when ) {
  67.             off = topLeft( theWindow->port.portBits.bounds );
  68.             SectRgn( theWindow->port.visRgn, theWindow->port.clipRgn, mask );
  69.             OffsetRgn( mask, -off.h, -off.v );
  70.             SectRgn( menuMask, mask, mask );
  71.             if( !EmptyRgn( mask )) {
  72.                 if( theData->allBitsState ) {
  73.                     SetPort( theWindow );
  74.                     fixAllBits( theData );
  75.                     SetPort( savePort );
  76.                 }
  77.                 doMenuCopy( &( theData->allBits ), dest, bounds, mask, off );
  78.             }
  79.         }
  80.         HUnlock( theDataHand );
  81.         theWindow = nextUserWindow( theWindow->nextWindow );
  82.     }
  83.     DisposeRgn( mask );
  84.     DisposeRgn( selMask );
  85. }
  86.  
  87. doMenuCopy( source, dest, bounds, mask, off )
  88.     BitMap        *source, *dest;
  89.     Rect            *bounds;
  90.     RgnHandle        mask;
  91.     Point            off;
  92.     {
  93.     Rect            tempRect;
  94.  
  95.     OffsetRect( &( source->bounds ), -off.h, -off.v );
  96.     if( SectRect( &( source->bounds ), bounds, &tempRect ))
  97.         CopyBits( source, dest, &tempRect, &tempRect, srcCopy, mask );
  98.     OffsetRect( &( source->bounds ), off.h, off.v );
  99.     }
  100.  
  101. /*******************************************************
  102. *                                                                *
  103. *                                                                *
  104. *******************************************************/
  105.  
  106. isScreen( map )
  107.     BitMap        *map;
  108.     {
  109.     if( map->rowBytes & 0x8000 )
  110.         return((( PixMapPtr )map )->baseAddr == ( **( **GetGDevice() ).gdPMap ).baseAddr );
  111.     else    return( map->baseAddr == screenBits.baseAddr );
  112.     }
  113.  
  114. /*******************************************************
  115. *                                                                *
  116. *                                                                *
  117. *******************************************************/
  118.  
  119. BitMap *fixPixPtr( thePtr )
  120.     BitMap        *thePtr;
  121.     {
  122.     if(( thePtr->rowBytes & 0xc000 ) == 0xc000 )
  123.         thePtr = *( BitMap ** )( thePtr->baseAddr );
  124.     return( thePtr );
  125.     }
  126.  
  127. fixCopy( source, dest, sRect, dRect, mode, mask )
  128.     BitMap        *source, *dest;
  129.     Rect            *sRect, *dRect;
  130.     int            mode;
  131.     RgnHandle        mask;
  132.     {
  133.     Rect            realRect;
  134.     RgnHandle        tempRgn, menuRgn;
  135.     rgnListHandle    theList;
  136.     rgnListPtr        rgns;
  137.     int            sScreen, dScreen, errno;
  138.     
  139.     source = fixPixPtr( source );
  140.     dest = fixPixPtr( dest );
  141.     sScreen = isScreen( source );
  142.     dScreen = isScreen( dest );
  143.     if( sScreen && !dScreen )
  144.         {
  145.         tempRgn = NewRgn();
  146.         menuRgn = NewRgn();
  147.         realRect = *sRect;
  148.         realRect.left += 3;
  149.         realRect.bottom -= 3;
  150.         realRect.right -= 3;
  151.         RectRgn( menuRgn, &realRect );
  152.         realRect.bottom += 1;
  153.         realRect.right += 1;
  154.         realRect.left += 3;
  155.         RectRgn( tempRgn, &realRect );
  156.         UnionRgn( tempRgn, menuRgn, menuRgn );
  157.         DisposeRgn( tempRgn );
  158.         theList = ( rgnListHandle )NewHandle(( long )sizeof( rgnList ));
  159.         if( errno = MemError() ) hardPanic( errno, memPanic );
  160.         if( menuRgns ) UnionRgn(( **menuRgns ).theRgn, menuRgn, menuRgn );
  161.         rgns = *theList;
  162.         rgns->next = menuRgns;
  163.         rgns->theRgn = menuRgn;
  164.         rgns->origRect = *sRect;
  165.         rgns->when = timer();
  166.         menuRgns = theList;
  167.         }
  168.     else if( dScreen && !sScreen )
  169.         {
  170.         if( EqualRect( dRect, &(( **menuRgns ).origRect )))        /* We must be undo-ing the last menu pull-down */
  171.             {
  172.             HLock( menuRgns );
  173.             rgns = *menuRgns;
  174.             tempRgn = NewRgn();
  175.             RectRgn( tempRgn, sRect );
  176.             theList = rgns->next;
  177.             if( theList )
  178.                 {
  179.                 HLock( theList );
  180.                 DiffRgn( tempRgn, ( **theList ).theRgn, tempRgn );
  181.                 HUnlock( theList );
  182.                 }
  183.             fixWindows( source, sRect, tempRgn, rgns->when );
  184.             DisposeRgn( tempRgn );
  185.             DisposeRgn( rgns->theRgn );
  186.             HUnlock( menuRgns );
  187.             DisposHandle( menuRgns );
  188.             menuRgns = theList;
  189.             }
  190.         }
  191.     }
  192.  
  193. /*******************************************************
  194. *                                                                *
  195. *                                                                *
  196. *******************************************************/
  197.  
  198. doCopyBits( mask, mode, dRect, sRect, dest, source )    /* reversed for pascal-ish-ness    */
  199.     BitMap    *source, *dest;
  200.     Rect        *sRect, *dRect;
  201.     int        mode;
  202.     RgnHandle    mask;
  203. {
  204.     int        height;
  205.     
  206.     asm {
  207.         movem.l    d0-d7/a1-a5,-(sp)
  208.         move.l    CurrentA5,a5
  209.     }
  210.     if( !isMyCopy ) {
  211.         startMyCopy();
  212.         height = getMBarHeight() + 8;
  213.         if( dRect->bottom - dRect->top >= height )
  214.             fixCopy( source, dest, sRect, dRect, mode, mask );
  215.         endMyCopy();
  216.     }    
  217.     asm {
  218.         movem.l    (sp)+,d0-d7/a1-a5
  219.         unlk        a6
  220.         move.l    oldCopyBits,a0
  221.         jmp        (a0)
  222.     }
  223. }
  224.  
  225. startMyCopy() {
  226.     ++isMyCopy;
  227. }
  228.  
  229. endMyCopy() {
  230.     --isMyCopy;
  231. }
  232.  
  233. /*******************************************************
  234. *                                                                *
  235. *    Sets the clipRgn of a window to its old clipRgn minus the part covered by the    *
  236. *    current menu region.  This it gets out of the (global) stack of regions.        *
  237. *                                                                *
  238. *******************************************************/
  239.  
  240. doMenuClip( saveClip )
  241. RgnHandle        saveClip;
  242. {
  243.     Point            off;
  244.     RgnHandle        newClip, theRgn;
  245.     
  246.     off = topLeft( thePort->portBits.bounds );
  247.     GetClip( saveClip );
  248.     if( menuRgns )
  249.         {
  250.         HLock( menuRgns );
  251.         newClip = NewRgn();
  252.         theRgn = ( **menuRgns ).theRgn;
  253.         OffsetRgn( theRgn, off.h, off.v );
  254.         DiffRgn( saveClip, theRgn, newClip );
  255.         OffsetRgn( theRgn, -off.h, -off.v );
  256.         SetClip( newClip );
  257.         DisposeRgn( newClip );
  258.         HUnlock( menuRgns );
  259.         }
  260.     }
  261.  
  262. /*******************************************************
  263. *                                                                *
  264. *    Doesn't care about params as it just installs some stuff when called.  On the    *
  265. *    PopUpMenuSelect trap, the menu tracking hooks are installed, PopUp is called    *
  266. *    and the menu hooks are removed.  This is an evil thing!  However, this will    *
  267. *    probably never be tail patched by apple.  To fix it, we need a reliable time to    *
  268. *    remove the menu hooks.                                            *
  269. *        Hmm - perhaps the menu hooks could be removed in the copyBits which    *
  270. *    restores the bits behind the topMost menu.  Only trouble is with the update    *
  271. *    mechanism which is used for low-memory situations                        *
  272. *                                                                *
  273. *******************************************************/
  274.  
  275. long pascal doPopUp( theMenu, top, left, item )
  276.     MenuHandle    theMenu;
  277.     int            top, left, item;
  278.     {
  279.     long            result;
  280.     
  281.     asm    {
  282.         movem.l    d0-d7/a1-a5,-(sp)
  283.         move.l    CurrentA5,a5
  284.         }
  285.     removePopUpTrap();
  286.     installMenuTrap();
  287.     asm    {
  288.         subq        #4,sp
  289.         move.l    theMenu,-(sp)
  290.         move    top,-(sp)
  291.         move    left,-(sp)
  292.         move    item,-(sp)
  293.         move.l    oldPopUp,a0
  294.         jsr        (a0)
  295.         move.l    (sp)+,result
  296.         }
  297.     removeMenuTrap();
  298.     installPopUpTrap();
  299.     asm    {
  300.         movem.l    (sp)+,d0-d7/a1-a5
  301.         }
  302.     return( result );
  303.     }
  304.  
  305. doSysMenu()
  306.     {
  307.     int        temp;
  308.     asm    {
  309.         movem.l    d0-d7/a1-a5,-(sp)
  310.         move.l    CurrentA5,a5
  311.         }
  312.     removeMenuTrap();
  313.     installModalTrap();
  314.     sysMenuActed = 1;
  315.     asm    {
  316.         move.l    oldSysMenu,a0
  317.         movem.l    (sp)+,d0-d7/a1-a5
  318.         unlk        a6
  319.         jmp        (a0)
  320.         }
  321.     }
  322.  
  323. /*******************************************************
  324. *                                                                *
  325. *                                                                *
  326. *******************************************************/
  327.  
  328. installMenuTrap() {
  329.     if( !menuTrapsOn ) {
  330.         installWaitTrap();
  331.         installDelayTrap();
  332.         oldSysMenu = NGetTrapAddress( SysMenuTrapNum, ToolTrap );
  333.         NSetTrapAddress( doSysMenu, SysMenuTrapNum, ToolTrap );
  334.         oldCopyBits = NGetTrapAddress( CopyBitsTrapNum, ToolTrap );
  335.         NSetTrapAddress( doCopyBits, CopyBitsTrapNum, ToolTrap );
  336.         isMyCopy = 0;
  337.         sysMenuActed = 0;
  338.     }
  339.     ++menuTrapsOn;
  340. }
  341.  
  342. removeMenuTrap() {
  343.     if( sysMenuActed ) {
  344.         removeModalTrap();
  345.         sysMenuActed = 0;
  346.     } else {
  347.         if( menuTrapsOn == 1 ) {
  348.             NSetTrapAddress( oldCopyBits, CopyBitsTrapNum, ToolTrap );
  349.             NSetTrapAddress( oldSysMenu, SysMenuTrapNum, ToolTrap );
  350.             removeDelayTrap();
  351.             removeWaitTrap();
  352.             ++isMyCopy;
  353.         }
  354.         if( menuTrapsOn > 0 ) --menuTrapsOn;
  355.     }
  356. }
  357.  
  358. installPopUpTrap() {
  359.     if( !popUpTrapOn ) {
  360.         oldPopUp = NGetTrapAddress( PopUpTrapNum, ToolTrap );
  361.         NSetTrapAddress( doPopUp, PopUpTrapNum, ToolTrap );
  362.     }
  363.     ++popUpTrapOn;
  364. }
  365.     
  366. removePopUpTrap() {
  367.     if( popUpTrapOn == 1 )
  368.         NSetTrapAddress( oldPopUp, PopUpTrapNum, ToolTrap );
  369.     if( popUpTrapOn > 0 ) --popUpTrapOn;
  370. }